package util

import (
	"bufio"
	"fmt"
	"io"
	"os"
)

const bufsize int = 10240

type readreturn struct {
	lines []string
	err error
}

func ReadFile(filepath string) []string {
	rm := readBlock(filepath,bufsize,processBlock)
	fmt.Sprintf("%s",rm.lines)
	return rm.lines
}

func ReadAndWriteFile(filepath string,outfilepath string){
	readBlockAndWrite(filepath,bufsize,writefile,outfilepath)
}

func ReadLine(filepath string) ( []string,error){
	var strs []string
	f, err := os.Open(filepath)
	if err != nil {
		panic(err)
	}
	defer f.Close()

	rd := bufio.NewReader(f)
	for {
		line, err := rd.ReadString('\n') //以'\n'为结束符读入一行

		if io.EOF == err {
			break
		}
		strs = append(strs,line)
	}
	return strs,nil

}

func readBlock(filepath string,bufsize int,hookfn func([]byte)(string)) readreturn {
	f, err := os.Open(filepath)
	var rm  readreturn
	var strs []string
	if err != nil {
		rm.err = err
		return  rm
	}
	defer f.Close()//defer后面必须是函数调用语句，不能是其他语句，否则编译器会出错。 这处代码类似于java中的finally关闭流操作

	buf := make([]byte,bufsize)//一次读取多少字节
	
	bfRd := bufio.NewReader(f)

	for  {
		n, err := bfRd.Read(buf)
		strs = append(strs,hookfn(buf[:n])) //n是成功读取的字节数

		if err != nil {//遇到任何错误立即返回，并忽略 EOF 错误信息
			if err == io.EOF {
				rm.err = nil
				return  rm
			}
			rm.err = err
			return  rm
		}
		rm.lines = strs
	}

	rm.err = nil
	return  rm
}

func readBlockAndWrite(filepath string,bufsize int,hookfn func(outfilepath string,line []byte),outfilepath string) error {
	f, err := os.Open(filepath)
	if err != nil {
		return  err
	}
	defer f.Close()//defer后面必须是函数调用语句，不能是其他语句，否则编译器会出错。 这处代码类似于java中的finally关闭流操作

	buf := make([]byte,bufsize)//一次读取多少字节

	bfRd := bufio.NewReader(f)

	for  {
		n, err := bfRd.Read(buf)
		hookfn(outfilepath,buf[:n])//n是成功读取的字节数

		if err != nil {//遇到任何错误立即返回，并忽略 EOF 错误信息
			if err == io.EOF {
				return nil
			}
			return err
		}
	}

	return nil
}


func writefile(outfilepath string,line []byte) {

	w,err :=os.OpenFile(outfilepath,os.O_RDWR|os.O_CREATE|os.O_APPEND,0644)
	checkError(err)

	_,err1 := w.Write(line)
	checkError(err1)

	errc := w.Close()
	checkError(errc)
}

func processBlock(line []byte) string {
	//os.Stdout.Write(line)
	return string(line)
}

func checkError(err error) error{
	if err != nil {//遇到任何错误立即返回，并忽略 EOF 错误信息
		if err == io.EOF {
			return nil
		}
		return err
	}
	return nil
}